package com.medical.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.medical.pojo.WeatherDailyResponse;
import com.medical.pojo.WeatherForecastResponse;
import com.medical.pojo.WeatherResponse;
import com.medical.service.WeatherService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.zip.GZIPInputStream;

@Service
@Slf4j
public class WeatherServiceImpl implements WeatherService {
    @Value("${weather.hefeng.key}")
    private String apiKey;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    private static final String BASE_URL = "https://devapi.qweather.com/v7";
    private static final String CACHE_WEATHER_PREFIX = "weather:";
    private static final long CACHE_WEATHER_NOW_TTL = 10;
    private static final long CACHE_WEATHER_FORECAST_TTL = 60;

    @Override
    public WeatherResponse getNowWeather(Double lat, Double lon) {
        String location = formatLocation(lon, lat);
        String cacheKey = CACHE_WEATHER_PREFIX + "now:" + location;

        try {
            // 尝试从缓存获取
            Object cachedData = redisTemplate.opsForValue().get(cacheKey);
            if (cachedData != null) {
                log.info("从缓存获取实时天气数据");
                return (WeatherResponse) cachedData;
            }

            String url = String.format("%s/weather/now?key=%s&location=%s",
                    BASE_URL, apiKey, location);
            log.info("调用和风天气API获取实时天气: {}", url);

            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.set(HttpHeaders.ACCEPT_ENCODING, "gzip");
            headers.set(HttpHeaders.ACCEPT, "application/json");

            HttpEntity<String> entity = new HttpEntity<>(headers);

            ResponseEntity<byte[]> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    byte[].class  // 改为接收字节数组
            );

            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                // 处理GZIP响应
                String responseBody;
                byte[] body = response.getBody();

                if (isGzipped(response.getHeaders())) {
                    try (GZIPInputStream gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(body))) {
                        responseBody = new String(gzipInputStream.readAllBytes(), StandardCharsets.UTF_8);
                    }
                } else {
                    responseBody = new String(body, StandardCharsets.UTF_8);
                }

                log.debug("API响应内容: {}", responseBody);

                WeatherResponse weatherResponse = JSONObject.parseObject(responseBody, WeatherResponse.class);
                if ("200".equals(weatherResponse.getCode())) {
                    redisTemplate.opsForValue().set(cacheKey, weatherResponse,
                            CACHE_WEATHER_NOW_TTL, TimeUnit.MINUTES);
                    return weatherResponse;
                }
            }
        } catch (Exception e) {
            log.error("获取实时天气数据失败: location={}", location, e);
        }
        return null;
    }

    private boolean isGzipped(HttpHeaders headers) {
        List<String> values = headers.get(HttpHeaders.CONTENT_ENCODING);
        return values != null && values.contains("gzip");
    }
    @Override
    public WeatherForecastResponse get24HourForecast(Double lat, Double lon) {
        String location = formatLocation(lon, lat);
        String cacheKey = CACHE_WEATHER_PREFIX + "24h:" + location;

        try {
            // 尝试从缓存获取
            Object cachedData = redisTemplate.opsForValue().get(cacheKey);
            if (cachedData != null) {
                return (WeatherForecastResponse) cachedData;
            }

            String url = String.format("%s/weather/24h?key=%s&location=%s",
                    BASE_URL, apiKey, location);
            log.info("调用和风天气API获取24小时预报: {}", url);

            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.set(HttpHeaders.ACCEPT_ENCODING, "gzip");
            headers.set(HttpHeaders.ACCEPT, "application/json");

            HttpEntity<String> entity = new HttpEntity<>(headers);

            ResponseEntity<byte[]> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    byte[].class
            );

            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                String responseBody = decompressResponse(response);
                log.debug("API响应内容: {}", responseBody);

                WeatherForecastResponse weatherResponse = JSON.parseObject(responseBody, WeatherForecastResponse.class);
                if ("200".equals(weatherResponse.getCode())) {
                    redisTemplate.opsForValue().set(cacheKey, weatherResponse,
                            CACHE_WEATHER_FORECAST_TTL, TimeUnit.MINUTES);
                    return weatherResponse;
                }
            }
        } catch (Exception e) {
            log.error("获取24小时预报失败: location={}", location, e);
        }
        return null;
    }

    // 添加新的辅助方法来处理响应解压
    private String decompressResponse(ResponseEntity<byte[]> response) throws IOException {
        byte[] body = response.getBody();
        if (body == null) {
            return "";
        }

        // 检查是否是GZIP压缩
        List<String> encodings = response.getHeaders().get(HttpHeaders.CONTENT_ENCODING);
        boolean isGzipped = encodings != null && encodings.contains("gzip");

        if (isGzipped) {
            try (GZIPInputStream gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(body));
                 ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
                byte[] buffer = new byte[1024];
                int len;
                while ((len = gzipInputStream.read(buffer)) > 0) {
                    outputStream.write(buffer, 0, len);
                }
                return outputStream.toString(StandardCharsets.UTF_8);
            }
        } else {
            return new String(body, StandardCharsets.UTF_8);
        }
    }

    @Override
    public WeatherDailyResponse get7DayForecast(Double lat, Double lon) {
        String location = formatLocation(lon, lat);
        String cacheKey = CACHE_WEATHER_PREFIX + "7d:" + location;

        try {
            // 尝试从缓存获取
            Object cachedData = redisTemplate.opsForValue().get(cacheKey);
            if (cachedData != null) {
                log.info("从缓存获取7天预报数据");
                return (WeatherDailyResponse) cachedData;
            }

            String url = String.format("%s/weather/7d?key=%s&location=%s",
                    BASE_URL, apiKey, location);
            log.info("调用和风天气API获取7天预报: {}", url);

            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.set(HttpHeaders.ACCEPT_ENCODING, "gzip");
            headers.set(HttpHeaders.ACCEPT, "application/json");

            HttpEntity<String> entity = new HttpEntity<>(headers);

            ResponseEntity<byte[]> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    byte[].class
            );

            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                String responseBody = decompressResponse(response);
                log.debug("API响应内容: {}", responseBody);

                WeatherDailyResponse weatherResponse = JSON.parseObject(responseBody, WeatherDailyResponse.class);
                if ("200".equals(weatherResponse.getCode())) {
                    redisTemplate.opsForValue().set(cacheKey, weatherResponse,
                            CACHE_WEATHER_FORECAST_TTL, TimeUnit.MINUTES);
                    return weatherResponse;
                }
            }
        } catch (Exception e) {
            log.error("获取7天预报失败: location={}", location, e);
        }
        return null;
    }

    private String formatLocation(Double lon, Double lat) {
        return String.format("%.6f,%.6f", lon, lat);
    }
}
